package com.hr.system.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.hr.common.annotation.Log;
import com.hr.common.constant.ClockStatusConstants;
import com.hr.common.constant.LeaveTypeConstans;
import com.hr.common.constant.UserConstants;
import com.hr.common.core.controller.BaseController;
import com.hr.common.core.domain.entity.SysUser;
import com.hr.common.utils.DateUtils;
import com.hr.system.ApprovalStatusEnum;
import com.hr.system.domain.*;
import com.hr.system.mapper.*;
import com.hr.system.utils.ClockUtils;
import com.hr.system.utils.SalaryNeedPayCount;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.hr.system.service.ISalaryService;
import com.hr.common.core.text.Convert;
import org.springframework.util.CollectionUtils;

/**
 * 员工工资Service业务层处理
 * 
 * @author ruoyi
 * @date 2021-02-26
 */
@Service
public class SalaryServiceImpl implements ISalaryService
{
    @Autowired
    private SalaryMapper salaryMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private ClockRuleMapper clockRuleMapper;

    @Autowired
    private SysPersonnelClockMapper sysPersonnelClockMapper;

    @Autowired
    private SysRuleMultipleMapper sysRuleMultipleMapper;

    @Autowired
    private SysOverWorkMapper sysOverWorkMapper;

    @Autowired
    private SysLeaveMapper sysLeaveMapper;

    @Autowired
    private BaseSalaryMapper baseSalaryMapper;

    @Autowired
    private SysAllowanceMapper sysAllowanceMapper;

    @Autowired
    private SysDeductionMapper sysDeductionMapper;

    protected final Logger logger = LoggerFactory.getLogger(SalaryServiceImpl.class);

    /**
     * 查询员工工资
     * 
     * @param id 员工工资ID
     * @return 员工工资
     */
    @Override
    public Salary selectSalaryById(Long id)
    {
        return salaryMapper.selectSalaryById(id);
    }

    /**
     * 查询员工工资列表
     * 
     * @param salary 员工工资
     * @return 员工工资
     */
    @Override
    public List<Salary> selectSalaryList(Salary salary)
    {
        return salaryMapper.selectSalaryList(salary);
    }

    @Override
    public List<Salary> selectMySalaryList(Salary mySalary) {
        return salaryMapper.selectMySalary(mySalary);
    }

    /**
     * 新增员工工资
     * 
     * @param salary 员工工资
     * @return 结果
     */
    @Override
    public int insertSalary(Salary salary)
    {
        return salaryMapper.insertSalary(salary);
    }

    /**
     * 修改员工工资
     * 
     * @param salary 员工工资
     * @return 结果
     */
    @Override
    public int updateSalary(Salary salary)
    {
        return salaryMapper.updateSalary(salary);
    }

    /**
     * 删除员工工资对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteSalaryByIds(String ids)
    {
        return salaryMapper.deleteSalaryByIds(Convert.toStrArray(ids));
    }

    @Override
    public List<Salary> selectSalaryByIds(String ids) {

        return salaryMapper.selectSalaryByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除员工工资信息
     * 
     * @param id 员工工资ID
     * @return 结果
     */
    @Override
    public int deleteSalaryById(Long id)
    {
        return salaryMapper.deleteSalaryById(id);
    }


    @Override
    public void salarySettlement() {
        //1、所有在职员工
        SysUser selectVO = new SysUser();
        selectVO.setStatus(UserConstants.NORMAL);
        selectVO.setDelFlag("0");
        List<SysUser> sysUsers = sysUserMapper.selectUserList(selectVO);
        System.out.println("sysUsers =====> " + sysUsers);
        sysUsers.forEach(sysUser -> {
            //租户的打卡规则
            ClockRule UserTenantClockRule = clockRuleMapper.selectClockRuleBytenantId(Integer.toUnsignedLong(sysUser.getTenantId()));
//            System.out.println("UserTenantClockRule ===========> " + UserTenantClockRule  + "租户id=>" +sysUser.getTenantId());
            //租户的奖惩规则
            SysRuleMultiple sysRuleMultiple = sysRuleMultipleMapper.selectSysRuleMultipleByTenantID(sysUser.getTenantId());
            //2、工作天数查询

            Salary salary = null;
            try {
                List<String> monthDays = DateUtils.getBetweenDays(DateUtils.getMonthFirstDayDate(), DateUtils.getMonthEndDayDate());
                List<String> allFreeDays = ClockUtils.getAllFreeDays(UserTenantClockRule);
                //去除节假日
                List<String> notHolidayMonthDays = ClockUtils.removeRepeatFactor(allFreeDays,monthDays);
                System.out.println("notHolidayMonthDays = " + notHolidayMonthDays.size());
                //去除周休息日
                List<String> notWorkWeeks = ClockUtils.getNotWorkWeeks(UserTenantClockRule);
                ClockUtils.removeNotWorkWeekEnd(notHolidayMonthDays, notWorkWeeks);
                //应工作天数
                int needWorkDays = notHolidayMonthDays.size();
                //3、当月考勤数据(加班，请假，迟到，早退)
                //迟到
                SysPersonnelClock clock = new SysPersonnelClock();
                clock.setTenantId(sysUser.getTenantId());
                clock.setPersonneId(sysUser.getUserId().intValue());
                clock.setClockState(ClockStatusConstants.LATER);
                List<SysPersonnelClock> LateClocks = sysPersonnelClockMapper.selectSysPersonnelClockList(clock);
                //计算迟到扣款
                Double lateDeduction = ClockUtils.calculateLateDeductions(LateClocks, UserTenantClockRule);
                //迟到扣款数（元/分钟 * 迟到分钟数）
                Double lateDeductionMoney = lateDeduction *  sysRuleMultiple.getLater().doubleValue();
                //早退
                clock.setClockState(ClockStatusConstants.EARLY_LEAVE);
                List<SysPersonnelClock> earlyLeaveClocks = sysPersonnelClockMapper.selectSysPersonnelClockList(clock);
                //计算早退分钟数
                Double lateDeductions = ClockUtils.calculateEarlyLeaveDeductions(earlyLeaveClocks, UserTenantClockRule);
                //早退扣款
                Double earlyLeaveDeductions = lateDeductions * sysRuleMultiple.getEarlyLeave().doubleValue();
                //加班
                SysOverWork sysOverWork = new SysOverWork();
                sysOverWork.setUserId(sysUser.getUserId());
                sysOverWork.setBeginTime(DateUtils.parseDate(DateUtils.getMonthFirstDayDate()));
                sysOverWork.setEndTime(DateUtils.parseDate(DateUtils.getMonthEndDayDate()));
                sysOverWork.setWorkStatus(ApprovalStatusEnum.APPROVAL_SUCCESS.getStatus());
                List<SysOverWork> sysOverWorkList = sysOverWorkMapper.selectSysOverWorkList(sysOverWork);
                //加班时间
                Double OvertimeHours = ClockUtils.calculateOvertimeHours(sysOverWorkList, sysRuleMultiple);
                //请假
                SysLeave sysLeave = new SysLeave();
                sysLeave.setTenantId(sysLeave.getTenantId());
                sysLeave.setUserId(sysUser.getUserId());
                sysLeave.setStartTime(DateUtils.parseDate(DateUtils.getMonthFirstDayDate()));
                sysLeave.setEndTime(DateUtils.parseDate(DateUtils.getMonthEndDayDate()));
                sysLeave.setLeaveStatus(ApprovalStatusEnum.APPROVAL_SUCCESS.getStatus());
                System.out.println("请假的查询参数 ============= " + sysLeave);
                List<SysLeave> sysLeaves = sysLeaveMapper.selectSysLeaveList(sysLeave);
                //请假时间
                Double leaveHours = ClockUtils.calculateLeaveHours(sysLeaves, sysRuleMultiple);
                //4、员工编号查询工资小项
                /*基础工资*/
                BaseSalary baseSalary = baseSalaryMapper.selectBaseSalaryByUserId(sysUser.getUserId().intValue());
                /*应发项目*/
                SysAllowance sysAllowance = sysAllowanceMapper.selectSysAllowanceByUserId(sysUser.getUserId());
                /*扣除项目*/
                SysDeduction sysDeduction = sysDeductionMapper.selectSysDeductionByUserId(sysUser.getUserId());
                //5、根据员工信息 + 月份 + 考勤数据 + 工资小项 ---> 生成工资条
                salary = new Salary();
                //基本信息
                salary.setUserId(sysUser.getUserId().intValue());
                salary.setUserName(sysUser.getUserName());
                salary.setTenantId(sysUser.getTenantId());
                salary.setSalaryMonth(DateUtils.dateTimeNow("yyyy-MM"));
                //工作天数
                salary.setDutyWorkDay(needWorkDays);
                salary.setActualWorkDay(needWorkDays - leaveHours.intValue() / 12 + OvertimeHours.intValue() / 12);
                //在职天数
                //基本工资
                salary.setBaseSalary(baseSalary.getBaseSalary());
                //补贴
                salary.setCommunicationAllowance(sysAllowance.getConmunictaionAllowance());
                salary.setMealAllowance(sysAllowance.getMealAllowance());
                salary.setExpatriateAllowance(sysAllowance.getExpatriateAllowance());
                salary.setLivingAllowance(sysAllowance.getLivingAllowance());
                salary.setTransportationAllowance(sysAllowance.getTransportationAllowance());
                salary.setTechnologyPositionAllowance(sysAllowance.getTechnologyPsotAllowance());
                salary.setManagementPositionAllowance(sysAllowance.getManagementPostAllowance());
                //加班信息
                salary.setOvertimeHours(OvertimeHours.intValue());
                BigDecimal multiply = new BigDecimal("1");
                multiply = new BigDecimal("8").multiply(new BigDecimal("24"));
                BigDecimal OvertimeMoneyPerHour = baseSalary.getBaseSalary().divide(multiply, 2, BigDecimal.ROUND_HALF_UP);
                salary.setOvertimePay(OvertimeMoneyPerHour.multiply(new BigDecimal(OvertimeHours)));
                //扣除项
                //五险一金扣除
                salary.setFiveInsurancesAndOneFund(sysDeduction.getFiveOne());
                salary.setPersonalTaxDeduction(sysDeduction.getPersonalTax());
                //迟到分钟数
                salary.setLateDeductionMinutes(lateDeductions.intValue());
                salary.setLateDeduction(new BigDecimal(lateDeductions).multiply(sysRuleMultiple.getLater()));
                //事假
                List<SysLeave> thingsLeave = sysLeaves.stream()
                        .filter(Leave -> Leave.getLeaveType().equals(LeaveTypeConstans.THING_HOLIDAY)).collect(Collectors.toList());
                BigDecimal thingsLeaveDays = SalaryNeedPayCount.caculateLeaveDays(thingsLeave);
                salary.setPersonalLeaveDays(thingsLeaveDays);
                salary.setPersonalLeaveDeduction(thingsLeaveDays.multiply(sysRuleMultiple.getThingLeave()));
                //病假
                List<SysLeave> sickLeave = sysLeaves.stream()
                        .filter(Leave -> Leave.getLeaveType().equals(LeaveTypeConstans.SICK_HOLIDAY)).collect(Collectors.toList());
                BigDecimal sickLeaveDays = SalaryNeedPayCount.caculateLeaveDays(sickLeave);
                salary.setSickLeaveDays(sickLeaveDays);
                salary.setSickLeaveDeduction(sickLeaveDays.multiply(sysRuleMultiple.getSickLeave()));

                //实发工资
                Double accPaySalary = SalaryNeedPayCount.salaryActualPayCaculete(salary);
                //应发工资
                Double needPaySalary = SalaryNeedPayCount.salaryNeedPayCaculete(salary);
                //6、工资应发与实发计算
                salary.setNeedPayTotal(new BigDecimal(needPaySalary));
                salary.setAcctralPayTotal(new BigDecimal(accPaySalary));
                salary.setBankAccount("13487441144541512154");
                salaryMapper.insertSalary(salary);
                System.out.println("===================薪资计算完成========================");
            }catch (Exception e) {
                logger.error(salary.getUserName()+"的薪资计算异常");
                e.printStackTrace();
            }
        });

    }



    public static void main(String[] args) {

    }
}
